from abc import ABC, abstractclassmethod, abstractmethod
from typing import Dict

from ..data_struct import Job
from ..job_store.interface import JobStore


class DuplicatePolicy(Exception):
    def __init__(self, name: str):
        self.name = name


class AddOrRunTimer(ABC):

    @abstractmethod
    def add_or_run(self, timer: Job) -> None:
        """添加或运行任务"""


class JobRetryPolicy(ABC):
    '''任务重试策略'''
    job_store: JobStore

    @abstractclassmethod
    def name(cls) -> str:
        '''策略名称'''

    @abstractmethod
    def retry(self, tw: AddOrRunTimer):
        '''重试控制逻辑接口'''

    def init(self, store):
        self.job_store = store


class PolicyPool:
    """重试策略池"""
    _policies: Dict[str, JobRetryPolicy] = {}

    def init(self, store):
        for _, policy in self._policies.items():
            policy.init(store)

    def register(self, policy: JobRetryPolicy):
        name = policy.name()
        if name in self._policies:
            raise DuplicatePolicy(name)
        self._policies[policy.name()] = policy()

    def get(self, name: str) -> JobRetryPolicy:
        return self._policies.get(name)


policy_pool = PolicyPool()